package com.gzs.learn.payment.algorithm;

import com.gzs.learn.common.util.JsonUtil;
import com.gzs.learn.payment.PaymentConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * DB分片算法
 */
@Slf4j
public abstract class BaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    private static final String SERIAL = PaymentConstants.DB_SHARD_SERIAL;
    private static final String ORDER_ID = PaymentConstants.DB_SHARD_ORDER_ID;
    private static final String MEMBER_ID = PaymentConstants.DB_SHARD_MEMBER_ID;
    private static final String REFUND_SERIAL = PaymentConstants.DB_SHARD_REFUND_SERIAL;

    abstract long getActualTarget(long shardingTarget);

    @Override
    public Collection<String> doSharding(Collection<String> targets, ComplexKeysShardingValue<Long> shardingValue) {
        log.debug("available target name:{}", JsonUtil.toJSONString(targets));
        List<String> shardingResults = new ArrayList<>();
        Map<String, Collection<Long>> nameAndValuesMap = shardingValue.getColumnNameAndShardingValuesMap();
        Collection<Long> serialList = nameAndValuesMap.get(SERIAL);
        Collection<Long> orderIdList = nameAndValuesMap.get(ORDER_ID);
        Collection<Long> memberIdList = nameAndValuesMap.get(MEMBER_ID);
        Collection<Long> refundSerialIdList = nameAndValuesMap.get(REFUND_SERIAL);
        // 默认-1,表示未传入分库键,落第一个库
        long shardingTarget = -1;
        String actualShardingKey = "";
        if (CollectionUtils.isNotEmpty(serialList)) {
            // 序列号
            shardingTarget = serialList.iterator().next();
            actualShardingKey = SERIAL;
        } else if (CollectionUtils.isNotEmpty(orderIdList)) {
            // 订单号
            shardingTarget = orderIdList.iterator().next();
            actualShardingKey = ORDER_ID;
        } else if (CollectionUtils.isNotEmpty(memberIdList)) {
            // 会员ID
            shardingTarget = memberIdList.iterator().next();
            actualShardingKey = MEMBER_ID;
        } else if (CollectionUtils.isNotEmpty(refundSerialIdList)) {
            // 退款流水号
            shardingTarget = refundSerialIdList.iterator().next();
            actualShardingKey = REFUND_SERIAL;
        }

        shardingTarget = getActualTarget(shardingTarget);

        // 无分库/分表列,默认走默认数据库
        if (shardingTarget == -1) {
            String target = targets.iterator().next();
            shardingResults.add(target);
            log.debug("real sharding info key:{},value:{},target:{}", actualShardingKey, shardingTarget, target);
            return shardingResults;
        }

        for (String target : targets) {
            if (target.endsWith(shardingTarget + "")) {
                shardingResults.add(target);
                log.debug("real sharding info key:{},value:{},target:{}", actualShardingKey, shardingTarget, target);
                break;
            }
        }

        return shardingResults;
    }
}
